﻿/*
 * File: Extenders.cs
 * Developer : Brent Larsen (brentoboy@gmail.com)
 * Date: 2011-AUG-9
 * Copyright (c) 2011 Brent Larsen.
 * Distributed under the terms of the GPL v3
 *  
 * This file is part of GenX-RPG
 * http://code.google.com/p/genx-rpg/ 
 * 
 * GenX-RPG is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GenX-RPG is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with GenX-RPG.  If not, see <http://www.gnu.org/licenses/>.
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SQLite;

namespace Rpg
{
    public static class Extenders
    {
        public static string f(this string format, params object[] args)
        {
            return String.Format(format, args);
        }

        public static string ToString_Safe(this object obj)
        {
            if (obj == null) 
                return null;
            else 
                return obj.ToString();
        }

        public static bool Contains(this string source, string value, StringComparison comp)
        {
            return source.IndexOf(value, comp) >= 0;
        }

        public static bool ContainsAll<T>(this IEnumerable<T> haystack, IEnumerable<T> needles)
        {
            foreach (var needle in needles)
            {
                if (!haystack.Contains(needle))
                    return false;
            }
            return true;
        }

        public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needles)
        {
            foreach (var needle in needles)
            {
                if (haystack.Contains(needle))
                    return true;
            }
            return false;
        }

        public static bool IsBlank(this string value)
        {
            if (value == null)
                return true;
            else if (value == string.Empty)
                return true;
            else if (value.Trim() == string.Empty)
                return true;
            else
                return false;
        }

        public static bool NotNull(this string value)
        {
            return value != null;
        }

        public static int? AsInt(this object value)
        {
            int? asInt = (value as int?);
            string asString = (value as string);

            if (asString != null)
            {
                int i;
                if (int.TryParse(asString, out i))
                    asInt = i;
            }

            return asInt;
        }

        public static decimal? AsDecimal(this object value)
        {
            decimal? asDecimal = (value as decimal?);
            string asString = (value as string);

            if (asString != null)
            {
                decimal d;
                if (decimal.TryParse(asString, System.Globalization.NumberStyles.AllowCurrencySymbol, null, out d))
                    asDecimal = d;
            }

            return asDecimal;
        }

        public static DateTime? AsDateTime(this object value)
        {
            var asDate = value as DateTime?;
            var asString = value as string;

            if (asString != null)
            {
                DateTime dt;
                if (DateTime.TryParse(asString, out dt))
                    asDate = dt;
            }

            return asDate;
        }

        public static bool? AsBool(this object value)
        {
            bool? asBool = (value as bool?);
            string asString = (value as string);

            if (asString != null)
            {
                bool b;
                if (bool.TryParse(asString, out b))
                    asBool = b;
            }

            return asBool;
        }

        public static byte? GetNullableByte(this System.Data.IDataReader reader, int index)
        {
            if (reader.IsDBNull(index))
                return null;
            else
                return reader.GetByte(index);
        }

        public static bool? GetNullableBoolean(this System.Data.IDataReader reader, int index)
        {
            if (reader.IsDBNull(index))
                return null;
            else
                return reader.GetBoolean(index);
        }

        public static DateTime? GetNullableDateTime(this System.Data.IDataReader reader, int index)
        {
            if (reader.IsDBNull(index))
                return null;
            else
                return reader.GetDateTime(index);
        }

        public static decimal? GetNullableDecimal(this System.Data.IDataReader reader, int index)
        {
            if (reader.IsDBNull(index))
                return null;
            else
                return reader.GetDecimal(index);
        }

        public static double? GetNullableDouble(this System.Data.IDataReader reader, int index)
        {
            if (reader.IsDBNull(index))
                return null;
            else
                return reader.GetDouble(index);
        }

        public static int? GetNullableInt32(this System.Data.IDataReader reader, int index)
        {
            if (reader.IsDBNull(index))
                return null;
            else
                return reader.GetInt32(index);
        }

        public static string GetNullableString(this System.Data.IDataReader reader, int index)
        {
            if (reader.IsDBNull(index))
                return null;
            else
                return reader.GetString(index);
        }

        public static IEnumerable<int?> GetListOfInts(this System.Data.IDataReader reader, int index)
        {
            return reader.GetNullableString(index).ToListOfNullableInts();
        }

        public static IEnumerable<int?> ToListOfNullableInts(this string value)
        {
            if (value.IsBlank())
                return null;

            return value.Split(',').Select(x => (int?)(x.AsInt()));
        }

        public static TValue TryGet<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
        {
            try
            {
                if (dictionary.ContainsKey(key))
                {
                    return dictionary[key];
                }
                else
                {
                    return default(TValue); // null for objects, "zero equivelant" for non-nullable types
                }
            }
            catch
            {
                return default(TValue);
            }
        }

        public static void AddOrUpdate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue value)
        {
            if (dictionary.ContainsKey(key))
            {
                dictionary[key] = value;
            }
            else
            {
                dictionary.Add(key, value);
            }
        }

        public static List<KeyValuePair<TKey, TValue>> ToKvpList<TKey, TValue>(this Dictionary<TKey, TValue> dictionary)
        {
            return dictionary.Select(x => new KeyValuePair<TKey, TValue>(x.Key, x.Value)).ToList();
        }

        public static SQLiteDataReader Query(this SQLiteConnection db, string sql, params object[] args)
        {
            using (var cmd = new SQLiteCommand((args != null && args.Any()) ? string.Format(sql, args) : sql, db))
            {
                return cmd.ExecuteReader();
            }
        }

        public static int Execute(this SQLiteConnection db, string sql, params object[] args)
        {
            using (var cmd = new SQLiteCommand((args != null && args.Any()) ? string.Format(sql, args) : sql, db))
            {
                return cmd.ExecuteNonQuery();
            }
        }

        public static object Get(this SQLiteConnection db, string sql, params object[] args)
        {
            using (var cmd = new SQLiteCommand((args != null && args.Any()) ? string.Format(sql, args) : sql, db))
            {
                return cmd.ExecuteScalar();
            }
        }

        public static string EncodeText(this SQLiteConnection db, string text)
        {
            return "'{0}'".f(text.Replace("'", "''"));
        }

        public static string GetUniqueStringID()
        {
            return Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0, 22).Replace("+", "_").Replace("/", "_"); // that last part lets us use these as filenames and as part of identifiers
        }
    }
}
